// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ShellLink.cs" company="Open Trader">
//   Copyright (c) David Denis (david.denis@systemathics.com)
// </copyright>
// <summary>
//   |  Open Trader - The Open Source Systematic Trading Platform
//   |
//   |  This program is free software: you can redistribute it and/or modify
//   |  it under the terms of the GNU General Public License as published by
//   |  the Free Software Foundation, either version 2 of the License, or
//   |  (at your option) any later version.
//   |
//   |  This program is distributed in the hope that it will be useful,
//   |  but WITHOUT ANY WARRANTY; without even the implied warranty of
//   |  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   |  GNU General Public License for more details.
//   |
//   |  You should have received a copy of the GNU General Public License
//   |  along with this program.  If not, see http://www.gnu.org/licenses
//   |
//   |  Up to date informations about Open Trader can be found at :
//   |    http://opentrader.org
//   |    http://opentrader.codeplex.com
//   |
//   |  For professional services, please visit us at :
//   |    http://www.systemathics.com
// </summary>
// --------------------------------------------------------------------------------------------------------------------

#pragma warning disable

namespace Org.OpenTrader.Extensions.Admin
{
#if ! AnyCPU

    #region

    using System;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Windows.Forms;

    #endregion

    #region ShellLink Object

    /// <summary>
    /// The shell link.
    /// </summary>
    [CLSCompliant(false)]
    public class ShellLink : IDisposable
    {
        #region Constants and Fields

        /// <summary>
        /// The link a.
        /// </summary>
        private IShellLinkA linkA;

        /// <summary>
        /// The link w.
        /// </summary>
        private IShellLinkW linkW;

        /// <summary>
        /// The shortcut file.
        /// </summary>
        private string shortcutFile = string.Empty;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="ShellLink"/> class.
        /// </summary>
        public ShellLink()
        {
            if (Environment.OSVersion.Platform == PlatformID.Win32NT)
            {
                this.linkW = (IShellLinkW)new CShellLink();
            }
            else
            {
                this.linkA = (IShellLinkA)new CShellLink();
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ShellLink"/> class.
        /// </summary>
        /// <param name="linkFile">
        /// The link file.
        /// </param>
        public ShellLink(string linkFile)
            : this()
        {
            this.Open(linkFile);
        }

        /// <summary>
        /// Finalizes an instance of the <see cref="ShellLink"/> class. 
        /// </summary>
        ~ShellLink()
        {
            this.Dispose();
        }

        #endregion

        #region Enums

        /// <summary>
        /// The e shell link resolve flags.
        /// </summary>
        [Flags]
        public enum EShellLinkResolveFlags : uint
        {
            /// <summary>
            /// The slranymatch.
            /// </summary>
            SLRANYMATCH = 0x2, 

            /// <summary>
            /// The slrinvokemsi.
            /// </summary>
            SLRINVOKEMSI = 0x80, 

            /// <summary>
            /// The slrnolinkinfo.
            /// </summary>
            SLRNOLINKINFO = 0x40, 

            /// <summary>
            /// The slrnoui.
            /// </summary>
            SLRNOUI = 0x1, 

            /// <summary>
            /// The slrnouiwithmsgpump.
            /// </summary>
            SLRNOUIWITHMSGPUMP = 0x101, 

            /// <summary>
            /// The slrnoupdate.
            /// </summary>
            SLRNOUPDATE = 0x8, 

            /// <summary>
            /// The slrnosearch.
            /// </summary>
            SLRNOSEARCH = 0x10, 

            /// <summary>
            /// The slrnotrack.
            /// </summary>
            SLRNOTRACK = 0x20, 

            /// <summary>
            /// The slrupdate.
            /// </summary>
            SLRUPDATE = 0x4
        }

        /// <summary>
        /// The link display mode.
        /// </summary>
        public enum LinkDisplayMode : uint
        {
            /// <summary>
            /// The edm normal.
            /// </summary>
            edmNormal = EShowWindowFlags.SWNORMAL, 

            /// <summary>
            /// The edm minimized.
            /// </summary>
            edmMinimized = EShowWindowFlags.SWSHOWMINNOACTIVE, 

            /// <summary>
            /// The edm maximized.
            /// </summary>
            edmMaximized = EShowWindowFlags.SWMAXIMIZE
        }

        /// <summary>
        /// The e shell link gp.
        /// </summary>
        private enum EShellLinkGP : uint
        {
            /// <summary>
            /// The slgpshortpath.
            /// </summary>
            SLGPSHORTPATH = 1, 

            /// <summary>
            /// The slgpuncpriority.
            /// </summary>
            SLGPUNCPRIORITY = 2
        }

        /// <summary>
        /// The e show window flags.
        /// </summary>
        [Flags]
        private enum EShowWindowFlags : uint
        {
            /// <summary>
            /// The swhide.
            /// </summary>
            SWHIDE = 0, 

            /// <summary>
            /// The swshownormal.
            /// </summary>
            SWSHOWNORMAL = 1, 

            /// <summary>
            /// The swnormal.
            /// </summary>
            SWNORMAL = 1, 

            /// <summary>
            /// The swshowminimized.
            /// </summary>
            SWSHOWMINIMIZED = 2, 

            /// <summary>
            /// The swshowmaximized.
            /// </summary>
            SWSHOWMAXIMIZED = 3, 

            /// <summary>
            /// The swmaximize.
            /// </summary>
            SWMAXIMIZE = 3, 

            /// <summary>
            /// The swshownoactivate.
            /// </summary>
            SWSHOWNOACTIVATE = 4, 

            /// <summary>
            /// The swshow.
            /// </summary>
            SWSHOW = 5, 

            /// <summary>
            /// The swminimize.
            /// </summary>
            SWMINIMIZE = 6, 

            /// <summary>
            /// The swshowminnoactive.
            /// </summary>
            SWSHOWMINNOACTIVE = 7, 

            /// <summary>
            /// The swshowna.
            /// </summary>
            SWSHOWNA = 8, 

            /// <summary>
            /// The swrestore.
            /// </summary>
            SWRESTORE = 9, 

            /// <summary>
            /// The swshowdefault.
            /// </summary>
            SWSHOWDEFAULT = 10, 

            /// <summary>
            /// The swmax.
            /// </summary>
            SWMAX = 10
        }

        #endregion

        #region Interfaces

        /// <summary>
        /// The i persist.
        /// </summary>
        [ComImport()]
        [Guid("0000010C-0000-0000-C000-000000000046")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        private interface IPersist
        {
            /// <summary>
            /// The get class id.
            /// </summary>
            /// <param name="pClassID">
            /// The p class id.
            /// </param>
            [PreserveSig]
            void GetClassID(out Guid pClassID);
        }

        /// <summary>
        /// The i persist file.
        /// </summary>
        [ComImport()]
        [Guid("0000010B-0000-0000-C000-000000000046")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        private interface IPersistFile
        {
            /// <summary>
            /// The get class id.
            /// </summary>
            /// <param name="pClassID">
            /// The p class id.
            /// </param>
            [PreserveSig]
            void GetClassID(out Guid pClassID);

            /// <summary>
            /// The is dirty.
            /// </summary>
            void IsDirty();

            /// <summary>
            /// The load.
            /// </summary>
            /// <param name="pszFileName">
            /// The psz file name.
            /// </param>
            /// <param name="mode">
            /// The mode.
            /// </param>
            void Load([MarshalAs(UnmanagedType.LPWStr)] string pszFileName, uint mode);

            /// <summary>
            /// The save.
            /// </summary>
            /// <param name="pszFileName">
            /// The psz file name.
            /// </param>
            /// <param name="fRemember">
            /// The f remember.
            /// </param>
            void Save(
                [MarshalAs(UnmanagedType.LPWStr)] string pszFileName, [MarshalAs(UnmanagedType.Bool)] bool fRemember);

            /// <summary>
            /// The save completed.
            /// </summary>
            /// <param name="pszFileName">
            /// The psz file name.
            /// </param>
            void SaveCompleted([MarshalAs(UnmanagedType.LPWStr)] string pszFileName);

            /// <summary>
            /// The get cur file.
            /// </summary>
            /// <param name="ppszFileName">
            /// The ppsz file name.
            /// </param>
            void GetCurFile([MarshalAs(UnmanagedType.LPWStr)] out string ppszFileName);
        }

        /// <summary>
        /// The i shell link a.
        /// </summary>
        [ComImport()]
        [Guid("000214EE-0000-0000-C000-000000000046")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        private interface IShellLinkA
        {
            /// <summary>
            /// The get path.
            /// </summary>
            /// <param name="pszFile">
            /// The psz file.
            /// </param>
            /// <param name="cchMaxPath">
            /// The cch max path.
            /// </param>
            /// <param name="pfd">
            /// The pfd.
            /// </param>
            /// <param name="fFlags">
            /// The f flags.
            /// </param>
            void GetPath(
                [Out()] [MarshalAs(UnmanagedType.LPStr)] StringBuilder pszFile, 
                int cchMaxPath, 
                ref WIN32FINDDATAA pfd, 
                uint fFlags);

            /// <summary>
            /// The get id list.
            /// </summary>
            /// <param name="ppidl">
            /// The ppidl.
            /// </param>
            void GetIDList(out IntPtr ppidl);

            /// <summary>
            /// The set id list.
            /// </summary>
            /// <param name="pidl">
            /// The pidl.
            /// </param>
            void SetIDList(IntPtr pidl);

            /// <summary>
            /// The get description.
            /// </summary>
            /// <param name="pszFile">
            /// The psz file.
            /// </param>
            /// <param name="cchMaxName">
            /// The cch max name.
            /// </param>
            void GetDescription([Out()] [MarshalAs(UnmanagedType.LPStr)] StringBuilder pszFile, int cchMaxName);

            /// <summary>
            /// The set description.
            /// </summary>
            /// <param name="pszName">
            /// The psz name.
            /// </param>
            void SetDescription([MarshalAs(UnmanagedType.LPStr)] string pszName);

            /// <summary>
            /// The get working directory.
            /// </summary>
            /// <param name="pszDir">
            /// The psz dir.
            /// </param>
            /// <param name="cchMaxPath">
            /// The cch max path.
            /// </param>
            void GetWorkingDirectory([Out()] [MarshalAs(UnmanagedType.LPStr)] StringBuilder pszDir, int cchMaxPath);

            /// <summary>
            /// The set working directory.
            /// </summary>
            /// <param name="pszDir">
            /// The psz dir.
            /// </param>
            void SetWorkingDirectory([MarshalAs(UnmanagedType.LPStr)] string pszDir);

            /// <summary>
            /// The get arguments.
            /// </summary>
            /// <param name="pszArgs">
            /// The psz args.
            /// </param>
            /// <param name="cchMaxPath">
            /// The cch max path.
            /// </param>
            void GetArguments([Out()] [MarshalAs(UnmanagedType.LPStr)] StringBuilder pszArgs, int cchMaxPath);

            /// <summary>
            /// The set arguments.
            /// </summary>
            /// <param name="pszArgs">
            /// The psz args.
            /// </param>
            void SetArguments([MarshalAs(UnmanagedType.LPStr)] string pszArgs);

            /// <summary>
            /// The get hotkey.
            /// </summary>
            /// <param name="pwHotkey">
            /// The pw hotkey.
            /// </param>
            void GetHotkey(out short pwHotkey);

            /// <summary>
            /// The set hotkey.
            /// </summary>
            /// <param name="pwHotkey">
            /// The pw hotkey.
            /// </param>
            void SetHotkey(short pwHotkey);

            /// <summary>
            /// The get show cmd.
            /// </summary>
            /// <param name="piShowCmd">
            /// The pi show cmd.
            /// </param>
            void GetShowCmd(out uint piShowCmd);

            /// <summary>
            /// The set show cmd.
            /// </summary>
            /// <param name="piShowCmd">
            /// The pi show cmd.
            /// </param>
            void SetShowCmd(uint piShowCmd);

            /// <summary>
            /// The get icon location.
            /// </summary>
            /// <param name="pszIconPath">
            /// The psz icon path.
            /// </param>
            /// <param name="cchIconPath">
            /// The cch icon path.
            /// </param>
            /// <param name="piIcon">
            /// The pi icon.
            /// </param>
            void GetIconLocation(
                [Out()] [MarshalAs(UnmanagedType.LPStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon);

            /// <summary>
            /// The set icon location.
            /// </summary>
            /// <param name="pszIconPath">
            /// The psz icon path.
            /// </param>
            /// <param name="iIcon">
            /// The i icon.
            /// </param>
            void SetIconLocation([MarshalAs(UnmanagedType.LPStr)] string pszIconPath, int iIcon);

            /// <summary>
            /// The set relative path.
            /// </summary>
            /// <param name="pszPathRel">
            /// The psz path rel.
            /// </param>
            /// <param name="reserved">
            /// The reserved.
            /// </param>
            void SetRelativePath([MarshalAs(UnmanagedType.LPStr)] string pszPathRel, uint reserved);

            /// <summary>
            /// The resolve.
            /// </summary>
            /// <param name="hWnd">
            /// The h wnd.
            /// </param>
            /// <param name="fFlags">
            /// The f flags.
            /// </param>
            void Resolve(IntPtr hWnd, uint fFlags);

            /// <summary>
            /// The set path.
            /// </summary>
            /// <param name="pszFile">
            /// The psz file.
            /// </param>
            void SetPath([MarshalAs(UnmanagedType.LPStr)] string pszFile);
        }

        /// <summary>
        /// The i shell link w.
        /// </summary>
        [ComImport()]
        [Guid("000214F9-0000-0000-C000-000000000046")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        private interface IShellLinkW
        {
            /// <summary>
            /// The get path.
            /// </summary>
            /// <param name="pszFile">
            /// The psz file.
            /// </param>
            /// <param name="cchMaxPath">
            /// The cch max path.
            /// </param>
            /// <param name="pfd">
            /// The pfd.
            /// </param>
            /// <param name="fFlags">
            /// The f flags.
            /// </param>
            void GetPath(
                [Out()] [MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, 
                int cchMaxPath, 
                ref WIN32FINDDATAW pfd, 
                uint fFlags);

            /// <summary>
            /// The get id list.
            /// </summary>
            /// <param name="ppidl">
            /// The ppidl.
            /// </param>
            void GetIDList(out IntPtr ppidl);

            /// <summary>
            /// The set id list.
            /// </summary>
            /// <param name="pidl">
            /// The pidl.
            /// </param>
            void SetIDList(IntPtr pidl);

            /// <summary>
            /// The get description.
            /// </summary>
            /// <param name="pszFile">
            /// The psz file.
            /// </param>
            /// <param name="cchMaxName">
            /// The cch max name.
            /// </param>
            void GetDescription([Out()] [MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxName);

            /// <summary>
            /// The set description.
            /// </summary>
            /// <param name="pszName">
            /// The psz name.
            /// </param>
            void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);

            /// <summary>
            /// The get working directory.
            /// </summary>
            /// <param name="pszDir">
            /// The psz dir.
            /// </param>
            /// <param name="cchMaxPath">
            /// The cch max path.
            /// </param>
            void GetWorkingDirectory([Out()] [MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);

            /// <summary>
            /// The set working directory.
            /// </summary>
            /// <param name="pszDir">
            /// The psz dir.
            /// </param>
            void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);

            /// <summary>
            /// The get arguments.
            /// </summary>
            /// <param name="pszArgs">
            /// The psz args.
            /// </param>
            /// <param name="cchMaxPath">
            /// The cch max path.
            /// </param>
            void GetArguments([Out()] [MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);

            /// <summary>
            /// The set arguments.
            /// </summary>
            /// <param name="pszArgs">
            /// The psz args.
            /// </param>
            void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);

            /// <summary>
            /// The get hotkey.
            /// </summary>
            /// <param name="pwHotkey">
            /// The pw hotkey.
            /// </param>
            void GetHotkey(out short pwHotkey);

            /// <summary>
            /// The set hotkey.
            /// </summary>
            /// <param name="pwHotkey">
            /// The pw hotkey.
            /// </param>
            void SetHotkey(short pwHotkey);

            /// <summary>
            /// The get show cmd.
            /// </summary>
            /// <param name="piShowCmd">
            /// The pi show cmd.
            /// </param>
            void GetShowCmd(out uint piShowCmd);

            /// <summary>
            /// The set show cmd.
            /// </summary>
            /// <param name="piShowCmd">
            /// The pi show cmd.
            /// </param>
            void SetShowCmd(uint piShowCmd);

            /// <summary>
            /// The get icon location.
            /// </summary>
            /// <param name="pszIconPath">
            /// The psz icon path.
            /// </param>
            /// <param name="cchIconPath">
            /// The cch icon path.
            /// </param>
            /// <param name="piIcon">
            /// The pi icon.
            /// </param>
            void GetIconLocation(
                [Out()] [MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon);

            /// <summary>
            /// The set icon location.
            /// </summary>
            /// <param name="pszIconPath">
            /// The psz icon path.
            /// </param>
            /// <param name="iIcon">
            /// The i icon.
            /// </param>
            void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);

            /// <summary>
            /// The set relative path.
            /// </summary>
            /// <param name="pszPathRel">
            /// The psz path rel.
            /// </param>
            /// <param name="reserved">
            /// The reserved.
            /// </param>
            void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, uint reserved);

            /// <summary>
            /// The resolve.
            /// </summary>
            /// <param name="hWnd">
            /// The h wnd.
            /// </param>
            /// <param name="fFlags">
            /// The f flags.
            /// </param>
            void Resolve(IntPtr hWnd, uint fFlags);

            /// <summary>
            /// The set path.
            /// </summary>
            /// <param name="pszFile">
            /// The psz file.
            /// </param>
            void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets Arguments.
        /// </summary>
        public string Arguments
        {
            get
            {
                var arguments = new StringBuilder(260, 260);
                if (this.linkA == null)
                {
                    this.linkW.GetArguments(arguments, arguments.Capacity);
                }
                else
                {
                    this.linkA.GetArguments(arguments, arguments.Capacity);
                }

                return arguments.ToString();
            }

            set
            {
                if (this.linkA == null)
                {
                    this.linkW.SetArguments(value);
                }
                else
                {
                    this.linkA.SetArguments(value);
                }
            }
        }

        /// <summary>
        /// Gets or sets Description.
        /// </summary>
        public string Description
        {
            get
            {
                var description = new StringBuilder(1024, 1024);
                if (this.linkA == null)
                {
                    this.linkW.GetDescription(description, description.Capacity);
                }
                else
                {
                    this.linkA.GetDescription(description, description.Capacity);
                }

                return description.ToString();
            }

            set
            {
                if (this.linkA == null)
                {
                    this.linkW.SetDescription(value);
                }
                else
                {
                    this.linkA.SetDescription(value);
                }
            }
        }

        /// <summary>
        /// Gets or sets DisplayMode.
        /// </summary>
        public LinkDisplayMode DisplayMode
        {
            get
            {
                uint cmd = 0;
                if (this.linkA == null)
                {
                    this.linkW.GetShowCmd(out cmd);
                }
                else
                {
                    this.linkA.GetShowCmd(out cmd);
                }

                return (LinkDisplayMode)cmd;
            }

            set
            {
                if (this.linkA == null)
                {
                    this.linkW.SetShowCmd((uint)value);
                }
                else
                {
                    this.linkA.SetShowCmd((uint)value);
                }
            }
        }

        /// <summary>
        /// Gets or sets HotKey.
        /// </summary>
        public Keys HotKey
        {
            get
            {
                short key = 0;
                if (this.linkA == null)
                {
                    this.linkW.GetHotkey(out key);
                }
                else
                {
                    this.linkA.GetHotkey(out key);
                }

                return (Keys)key;
            }

            set
            {
                if (this.linkA == null)
                {
                    this.linkW.SetHotkey((short)value);
                }
                else
                {
                    this.linkA.SetHotkey((short)value);
                }
            }
        }

        /// <summary>
        /// Gets or sets IconIndex.
        /// </summary>
        public int IconIndex
        {
            get
            {
                var iconPath = new StringBuilder(260, 260);
                var iconIndex = 0;
                if (this.linkA == null)
                {
                    this.linkW.GetIconLocation(iconPath, iconPath.Capacity, out iconIndex);
                }
                else
                {
                    this.linkA.GetIconLocation(iconPath, iconPath.Capacity, out iconIndex);
                }

                return iconIndex;
            }

            set
            {
                var iconPath = new StringBuilder(260, 260);
                var iconIndex = 0;
                if (this.linkA == null)
                {
                    this.linkW.GetIconLocation(iconPath, iconPath.Capacity, out iconIndex);
                }
                else
                {
                    this.linkA.GetIconLocation(iconPath, iconPath.Capacity, out iconIndex);
                }

                if (this.linkA == null)
                {
                    this.linkW.SetIconLocation(iconPath.ToString(), value);
                }
                else
                {
                    this.linkA.SetIconLocation(iconPath.ToString(), value);
                }
            }
        }

        /// <summary>
        /// Gets or sets IconPath.
        /// </summary>
        public string IconPath
        {
            get
            {
                var iconPath = new StringBuilder(260, 260);
                var iconIndex = 0;
                if (this.linkA == null)
                {
                    this.linkW.GetIconLocation(iconPath, iconPath.Capacity, out iconIndex);
                }
                else
                {
                    this.linkA.GetIconLocation(iconPath, iconPath.Capacity, out iconIndex);
                }

                return iconPath.ToString();
            }

            set
            {
                var iconPath = new StringBuilder(260, 260);
                var iconIndex = 0;
                if (this.linkA == null)
                {
                    this.linkW.GetIconLocation(iconPath, iconPath.Capacity, out iconIndex);
                }
                else
                {
                    this.linkA.GetIconLocation(iconPath, iconPath.Capacity, out iconIndex);
                }

                if (this.linkA == null)
                {
                    this.linkW.SetIconLocation(value, iconIndex);
                }
                else
                {
                    this.linkA.SetIconLocation(value, iconIndex);
                }
            }
        }

        /// <summary>
        /// Gets or sets ShortCutFile.
        /// </summary>
        public string ShortCutFile
        {
            get
            {
                return this.shortcutFile;
            }

            set
            {
                this.shortcutFile = value;
            }
        }

        /// <summary>
        /// Gets or sets Target.
        /// </summary>
        public string Target
        {
            get
            {
                var target = new StringBuilder(260, 260);
                if (this.linkA == null)
                {
                    var fd = new WIN32FINDDATAW();
                    this.linkW.GetPath(target, target.Capacity, ref fd, (uint)EShellLinkGP.SLGPUNCPRIORITY);
                }
                else
                {
                    var fd = new WIN32FINDDATAA();
                    this.linkA.GetPath(target, target.Capacity, ref fd, (uint)EShellLinkGP.SLGPUNCPRIORITY);
                }

                return target.ToString();
            }

            set
            {
                if (this.linkA == null)
                {
                    this.linkW.SetPath(value);
                }
                else
                {
                    this.linkA.SetPath(value);
                }
            }
        }

        /// <summary>
        /// Gets or sets WorkingDirectory.
        /// </summary>
        public string WorkingDirectory
        {
            get
            {
                var path = new StringBuilder(260, 260);
                if (this.linkA == null)
                {
                    this.linkW.GetWorkingDirectory(path, path.Capacity);
                }
                else
                {
                    this.linkA.GetWorkingDirectory(path, path.Capacity);
                }

                return path.ToString();
            }

            set
            {
                if (this.linkA == null)
                {
                    this.linkW.SetWorkingDirectory(value);
                }
                else
                {
                    this.linkA.SetWorkingDirectory(value);
                }
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// The open.
        /// </summary>
        /// <param name="linkFile">
        /// The link file.
        /// </param>
        public void Open(string linkFile)
        {
            this.Open(linkFile, IntPtr.Zero, EShellLinkResolveFlags.SLRANYMATCH | EShellLinkResolveFlags.SLRNOUI, 1);
        }

        /// <summary>
        /// The open.
        /// </summary>
        /// <param name="linkFile">
        /// The link file.
        /// </param>
        /// <param name="hWnd">
        /// The h wnd.
        /// </param>
        /// <param name="resolveFlags">
        /// The resolve flags.
        /// </param>
        public void Open(string linkFile, IntPtr hWnd, EShellLinkResolveFlags resolveFlags)
        {
            this.Open(linkFile, hWnd, resolveFlags, 1);
        }

        /// <summary>
        /// The open.
        /// </summary>
        /// <param name="linkFile">
        /// The link file.
        /// </param>
        /// <param name="hWnd">
        /// The h wnd.
        /// </param>
        /// <param name="resolveFlags">
        /// The resolve flags.
        /// </param>
        /// <param name="timeOut">
        /// The time out.
        /// </param>
        public void Open(string linkFile, IntPtr hWnd, EShellLinkResolveFlags resolveFlags, ushort timeOut)
        {
            uint flags;

            if ((resolveFlags & EShellLinkResolveFlags.SLRNOUI) == EShellLinkResolveFlags.SLRNOUI)
            {
                flags = (uint)((int)resolveFlags | (timeOut << 16));
            }
            else
            {
                flags = (uint)resolveFlags;
            }

            if (this.linkA == null)
            {
                this.linkW.Resolve(hWnd, flags);
                this.shortcutFile = linkFile;
            }
            else
            {
                this.linkA.Resolve(hWnd, flags);
                this.shortcutFile = linkFile;
            }
        }

        /// <summary>
        /// The save.
        /// </summary>
        public void Save()
        {
            this.Save(this.shortcutFile);
        }

        /// <summary>
        /// The save.
        /// </summary>
        /// <param name="linkFile">
        /// The link file.
        /// </param>
        public void Save(string linkFile)
        {
            if (this.linkA == null)
            {
                ((IPersistFile)this.linkW).Save(linkFile, true);
                this.shortcutFile = linkFile;
            }
            else
            {
                ((IPersistFile)this.linkA).Save(linkFile, true);
                this.shortcutFile = linkFile;
            }
        }

        #endregion

        #region Implemented Interfaces

        #region IDisposable

        /// <summary>
        /// The dispose.
        /// </summary>
        public void Dispose()
        {
            if (this.linkW != null)
            {
                Marshal.ReleaseComObject(this.linkW);
                this.linkW = null;
            }

            if (this.linkA != null)
            {
                Marshal.ReleaseComObject(this.linkA);
                this.linkA = null;
            }
        }

        #endregion

        #endregion

        /// <summary>
        /// The filetime.
        /// </summary>
        [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 0)]
        private struct FILETIME
        {
            /// <summary>
            /// The low date time.
            /// </summary>
            public uint LowDateTime;

            /// <summary>
            /// The high date time.
            /// </summary>
            public uint HighDateTime;
        }

        /// <summary>
        /// The wi n 32 finddataa.
        /// </summary>
        [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 0, CharSet = CharSet.Ansi)]
        private struct WIN32FINDDATAA
        {
            /// <summary>
            /// The file attributes.
            /// </summary>
            public uint FileAttributes;

            /// <summary>
            /// The creation time.
            /// </summary>
            public FILETIME CreationTime;

            /// <summary>
            /// The last access time.
            /// </summary>
            public FILETIME LastAccessTime;

            /// <summary>
            /// The last write time.
            /// </summary>
            public FILETIME LastWriteTime;

            /// <summary>
            /// The file size high.
            /// </summary>
            public uint FileSizeHigh;

            /// <summary>
            /// The file size low.
            /// </summary>
            public uint FileSizeLow;

            /// <summary>
            /// The reserved 0.
            /// </summary>
            public uint Reserved0;

            /// <summary>
            /// The reserved 1.
            /// </summary>
            public uint Reserved1;

            /// <summary>
            /// The file name.
            /// </summary>
            public string FileName;

            /// <summary>
            /// The alternate file name.
            /// </summary>
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
            public string AlternateFileName;
        }

        /// <summary>
        /// The wi n 32 finddataw.
        /// </summary>
        [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 0, CharSet = CharSet.Unicode)]
        private struct WIN32FINDDATAW
        {
            /// <summary>
            /// The file attributes.
            /// </summary>
            public uint FileAttributes;

            /// <summary>
            /// The creation time.
            /// </summary>
            public FILETIME CreationTime;

            /// <summary>
            /// The last access time.
            /// </summary>
            public FILETIME LastAccessTime;

            /// <summary>
            /// The last write time.
            /// </summary>
            public FILETIME LastWriteTime;

            /// <summary>
            /// The file size high.
            /// </summary>
            public uint FileSizeHigh;

            /// <summary>
            /// The file size low.
            /// </summary>
            public uint FileSizeLow;

            /// <summary>
            /// The reserved 0.
            /// </summary>
            public uint Reserved0;

            /// <summary>
            /// The reserved 1.
            /// </summary>
            public uint Reserved1;

            /// <summary>
            /// The file name.
            /// </summary>
            public string FileName;

            /// <summary>
            /// The alternate file name.
            /// </summary>
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
            public string AlternateFileName;
        }

        /// <summary>
        /// The c shell link.
        /// </summary>
        [Guid("00021401-0000-0000-C000-000000000046")]
        [ClassInterface(ClassInterfaceType.None)]
        [ComImport()]
        private class CShellLink
        {
        }

        /// <summary>
        /// The un managed methods.
        /// </summary>
        private class UnManagedMethods
        {
            #region Methods

            /// <summary>
            /// The destroy icon.
            /// </summary>
            /// <param name="hIcon">
            /// The h icon.
            /// </param>
            /// <returns>
            /// The destroy icon.
            /// </returns>
            [DllImport("user32")]
            internal static extern int DestroyIcon(IntPtr hIcon);

            /// <summary>
            /// The extract icon ex.
            /// </summary>
            /// <param name="lpszFile">
            /// The lpsz file.
            /// </param>
            /// <param name="nIconIndex">
            /// The n icon index.
            /// </param>
            /// <param name="phIconLarge">
            /// The ph icon large.
            /// </param>
            /// <param name="phIconSmall">
            /// The ph icon small.
            /// </param>
            /// <param name="nIcons">
            /// The n icons.
            /// </param>
            /// <returns>
            /// The extract icon ex.
            /// </returns>
            [DllImport("Shell32", CharSet = CharSet.Auto)]
            internal static extern int ExtractIconEx(
                [MarshalAs(UnmanagedType.LPTStr)] string lpszFile, 
                int nIconIndex, 
                IntPtr[] phIconLarge, 
                IntPtr[] phIconSmall, 
                int nIcons);

            #endregion
        }
    }

    #endregion

#endif
}